package qc.module.qms.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qc.common.core.enums.qms.QmsManualTaskStatusEnum;
import qc.common.core.enums.qms.QmsManualTaskTypeEnum;
import qc.common.core.enums.qms.QmsPointTimeSegmentEnum;
import qc.common.core.utils.IdentifierUtil;
import qc.common.core.utils.LocalDateTimeUtil;
import qc.module.qms.dto.mq.QmsMqManualTaskCalcPointDataMessageDto;
import qc.module.qms.dto.task.ManualTaskOperateResultDto;
import qc.module.qms.entity.QmsManualTask;
import qc.module.qms.entity.QmsManualTaskWbs;
import qc.module.qms.entity.QmsPoint;
import qc.module.qms.repository.QmsManualTaskRepository;
import qc.module.qms.repository.QmsManualTaskWbsRepository;
import qc.module.qms.service.producer.QmsManualTaskProducer;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * QMS长耗时人工任务Service
 *
 * @author QuCheng Tech
 * @since 2025/10/14
 */
@Service
public class QmsManualTaskService {
    private static final Logger logger = LoggerFactory.getLogger(QmsManualTaskService.class);

    @Autowired
    private QmsManualTaskRepository manualTaskRepository;

    @Autowired
    private QmsManualTaskWbsRepository manualTaskWbsRepository;

    @Autowired
    private QmsBasicConfigCacheGetService basicConfigCacheGetService;

    @Autowired
    private QmsManualTaskProducer manualTaskProducer;

    /**
     * 人工长耗时任务模块说明：
     * 需要有的方法：新增、取消、查询待执行、更新状态、查询记录；不能对任务进行修改和删除
     *
     * 新增任务处理流程
     * 1.由controller中对新增任务传入的条件和参数进行判断和处理，在service中传入针对每种任务所需的信息；
     * 2.任务在写入时需要判断是否已有（执行中、待执行）相同的任务或者包含的任务，如果已有不重复添加
     *      判断重复的方法：逐个传入的信息在任务分解表中查询是否存在有在执行中或未执行的，如果存在表示任务重复，此任务分解不进行添加；
     *      任务分解表，用于记录明细（分解为单个点号、单个原始站点、模块编号、）可以用于判断是否已有相同任务
     * 3.任务新增后优先采用发送对应消息到MQ中，如果发送消息失败则有定时任务从任务分解表中进行查询任务进行执行；
     *
     */

    /**
     * 添加处理原始数据任务
     *
     * @param title       任务标题
     * @param content     任务的内容和说明
     * @param tablecode   原始数据库表编码
     * @param rawStcds    原始数据站点编码集合
     * @param columnCodes 原始数据库表列编码集合
     * @param beginTime   起始时间点
     * @param endTime     截止时间点
     * @param userId      创建任务的用户ID
     * @param userName    创建任务的用户名
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/29
     */
    public ManualTaskOperateResultDto addProcessRawDataTask(String title, String content, String tablecode, List<String> rawStcds, List<String> columnCodes,
                                                            LocalDateTime beginTime, LocalDateTime endTime, int userId, String userName) {
        return null;
    }

    /**
     * 添加计算点号数据任务
     *
     * @param title     任务标题
     * @param content   任务的内容和说明
     * @param pointIds  点号ID集合
     * @param tmseg     点号时段类型
     * @param beginTime 起始时间点
     * @param endTime   截止时间点
     * @param userId    创建任务的用户ID
     * @param userName  创建任务的用户名
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/29
     */
    public ManualTaskOperateResultDto addCalcPointDataTask(String title, String content, List<String> pointIds, QmsPointTimeSegmentEnum tmseg,
                                                           LocalDateTime beginTime, LocalDateTime endTime, int userId, String userName) {
        //初始化返回结果，先设置是否成功为false、各数量均为0
        ManualTaskOperateResultDto result = new ManualTaskOperateResultDto();
        result.setSuccess(false);
        result.setSuccesscount(0x0);
        result.setFailcount(0x0);
        result.setCancelcount(0x0);

        if (StringUtils.isBlank(title)) {
            result.setMsg("任务标题不能为空");
            return result;
        }
        if (StringUtils.isBlank(content)) {
            result.setMsg("任务内容说明不能为空");
            return result;
        }
        if (pointIds == null || pointIds.size() < 0x1) {
            result.setMsg("要计算的点号编码不能为空");
            return result;
        }
        if (tmseg == null || tmseg == QmsPointTimeSegmentEnum.UN_DEFINE) {
            result.setMsg("要计算的点号时段类型不能为空或未定义");
            return result;
        }
        if (beginTime == null) {
            result.setMsg("要计算点号的起始时间不能为空");
            return result;
        }
        if (endTime == null) {
            result.setMsg("要计算点号的截止时间不能为空");
            return result;
        }
        if (beginTime.isAfter(endTime)) {
            result.setMsg("要计算点号的起始时间不能大于截止时间");
            return result;
        }

        LocalDateTime now = LocalDateTimeUtil.getNow();
        //自动生成一个任务ID
        String taskid = IdentifierUtil.randomUUID();

        //需要先逐个分解项判断是否已有，如果全部都已有不进行添加；需要在所有任务分解项判断和添加完成后再添加任务
        int taskWbsCount = 0x0;
        //要发送到MQ的计算点号数据消息集合，每个任务分解项单独作为一条消息；需要在发送消息前再根据点号的计算顺序进行一次排序后再进行发送
        List<QmsMqManualTaskCalcPointDataMessageDto> messages = new ArrayList<>();
        StringBuilder sbTaskWbsValidResult = new StringBuilder();
        for (String pointId : pointIds) {
            //获取点号信息，判断点号是否有效，同时需要获取点号的名称和计算顺序
            QmsPoint point = basicConfigCacheGetService.getPoint(pointId);
            if (point == null) {
                sbTaskWbsValidResult.append("点号编码[" + pointId + "]无对应的点号信息，请确认点号编码是否正确。");
            } else {
                //如果已存在相同的任务分解项，在提示信息中增加并返回
                boolean hasExist = hasExistCalcPointDataTaskWbs(pointId, tmseg, beginTime, endTime);
                if (hasExist == true) {
                    sbTaskWbsValidResult.append("点号[" + point.getPointname() + "]已存在包含当前计算时间段的计算任务，请等待已有任务执行，无需重复添加。");
                } else {
                    //生成任务分解ID
                    String wbsid = IdentifierUtil.randomUUID();

                    QmsManualTaskWbs taskWbsEntity = new QmsManualTaskWbs();
                    taskWbsEntity.setWbsid(wbsid);
                    taskWbsEntity.setTaskid(taskid);
                    taskWbsEntity.setTasktype(QmsManualTaskTypeEnum.CALC_POINT_DATA);//固定设置任务类型为计算点号数据
                    taskWbsEntity.setPointid(pointId);
                    taskWbsEntity.setTmseg(tmseg);
                    taskWbsEntity.setDatabegintm(beginTime);
                    taskWbsEntity.setDataendtm(endTime);
                    taskWbsEntity.setTaskstatus(QmsManualTaskStatusEnum.PENDING);//固定设置任务状态为待执行
                    //初始化发送到MQ的状态为true，并设置发送时间
                    taskWbsEntity.setHassend(true);
                    taskWbsEntity.setSendtm(now);
                    //设置任务的写入时间和更新时间均为当前时间
                    taskWbsEntity.setIntm(now);
                    taskWbsEntity.setUptm(now);

                    if (manualTaskWbsRepository.insert(taskWbsEntity) > 0x0) {
                        //写入任务分解表成功后才累加任务总数
                        taskWbsCount++;
                        //添加到需要发送至MQ的消息
                        QmsMqManualTaskCalcPointDataMessageDto message = new QmsMqManualTaskCalcPointDataMessageDto();
                        message.setTaskid(taskid);
                        message.setWbsid(wbsid);
                        message.setPointid(pointId);
                        //获取点号的信息，设置消息中的点号名称和计算顺序
                        message.setPointname(point.getPointname());
                        message.setCalcodr(point.getCalcodr());
                        message.setTmseg(tmseg);
                        message.setBegintm(beginTime);
                        message.setTendtm(endTime);

                        messages.add(message);
                    }
                }
            }
        }
        if (sbTaskWbsValidResult.length() > 0x0)
            result.setMsg(sbTaskWbsValidResult.toString());

        if (taskWbsCount < 0x1) {
            //如果最终添加的任务分解项数量为0，表示错误，不需要添加任务和任务分解项
            result.setMsg("所有点号均存在包含当前计算时间段的计算任务，请等待已有任务执行，无需重复添加。");
        } else {
            //创建任务信息Entity并赋值
            QmsManualTask taskEntity = new QmsManualTask();
            taskEntity.setId(taskid);
            taskEntity.setTitle(title);
            taskEntity.setContent(content);
            taskEntity.setTasktype(QmsManualTaskTypeEnum.CALC_POINT_DATA);//固定设置任务类型为计算点号数据
            if (userId > 0x0)
                taskEntity.setUserid(userId);
            if (StringUtils.isNotBlank(userName))
                taskEntity.setUsername(userName);
            taskEntity.setDatabegintm(beginTime);
            taskEntity.setDataendtm(endTime);
            taskEntity.setTaskstatus(QmsManualTaskStatusEnum.PENDING);//固定设置任务状态为待执行
            //任务的分解项数量不是传入的点号集合数量，需要使用实际添加的任务分解项数量
            taskEntity.setTotalcount(taskWbsCount);
            //任务创建时初始化时固定设置任务的成功和失败数量均为0
            taskEntity.setSuccesscount(0x0);
            taskEntity.setFailcount(0x0);
            //设置任务的写入时间和更新时间均为当前时间
            taskEntity.setIntm(now);
            taskEntity.setUptm(now);

            manualTaskRepository.insert(taskEntity);
            //添加完成
            result.setSuccess(true);
            result.setTaskid(taskid);
            result.setTotalcount(taskWbsCount);

            //发送至MQ消息，需要根据点号中的计算顺序重新对消息进行排序后进行发送
            if (messages.size() > 0x0) {
                List<QmsMqManualTaskCalcPointDataMessageDto> orderByCalcOrderMessages = messages.stream().sorted(Comparator.comparingInt(QmsMqManualTaskCalcPointDataMessageDto::getCalcodr)).collect(Collectors.toList());
                for (QmsMqManualTaskCalcPointDataMessageDto message : orderByCalcOrderMessages) {
                    //只需要发送，不管发送到MQ是否成功；如果发送成功由对应的消费者进行处理，如果发送不成功由定时任务查询取出后进行处理
                    //需要获取发送状态，先写入数据库中的发送到MQ标记为true，如果发送失败在此修改为false；默认情况下均应是发送成功
                    String sendTaskWbsResult = manualTaskProducer.sendCalcPointDataMessage(message);
                    if (StringUtils.isNotBlank(sendTaskWbsResult)) {
                        //发送至MQ失败，修改已经写入任务分解表中的发送标记
                        LambdaUpdateWrapper<QmsManualTaskWbs> wrapper = new LambdaUpdateWrapper<>();

                        wrapper.set(QmsManualTaskWbs::getHassend, false);
                        wrapper.set(QmsManualTaskWbs::getSendtm, null);

                        wrapper.eq(QmsManualTaskWbs::getWbsid, message.getWbsid());

                        manualTaskWbsRepository.update(null, wrapper);
                    }
                }
            }
        }

        return result;
    }

    /**
     * 判断是否已有执行中或待执行的计算点号数据任务分解项
     *
     * @param pointId   点号
     * @param tmseg     点号时段类型
     * @param beginTime 起始时间
     * @param endTime   截止时间
     * @return boolean
     * @author QuCheng Tech
     * @since 2025/10/29
     */
    private boolean hasExistCalcPointDataTaskWbs(String pointId, QmsPointTimeSegmentEnum tmseg, LocalDateTime beginTime, LocalDateTime endTime) {
        LambdaQueryWrapper<QmsManualTaskWbs> wrapper = new LambdaQueryWrapper<>();
        //只用于判断是否存在已有记录，只查询wbsid列
        wrapper.select(QmsManualTaskWbs::getWbsid);
        //任务类型：必须时计算点号数据
        wrapper.eq(QmsManualTaskWbs::getTasktype, QmsManualTaskTypeEnum.CALC_POINT_DATA);
        //任务状态：待执行或执行中
        wrapper.le(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PROCESSING);
        //查询条件：点号、时段类型相同，时间段必须完全包含在内（只包含一部分的不作为已有相同任务）
        wrapper.eq(QmsManualTaskWbs::getPointid, pointId);
        wrapper.eq(QmsManualTaskWbs::getTmseg, tmseg);
        wrapper.ge(QmsManualTaskWbs::getDatabegintm, beginTime);
        wrapper.le(QmsManualTaskWbs::getDataendtm, endTime);

        long count = manualTaskWbsRepository.selectCount(wrapper);
        if (count > 0x0)
            return true;

        return false;
    }

    /**
     * 添加转发点号数据任务
     *
     * @param title      任务标题
     * @param content    任务的内容和说明
     * @param systemCode 转发系统编码
     * @param pointIds   点号ID集合
     * @param tmsegs     点号时段类型集合
     * @param beginTime  起始时间点
     * @param endTime    截止时间点
     * @param userId     创建任务的用户ID
     * @param userName   创建任务的用户名
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/29
     */
    public ManualTaskOperateResultDto addForwardPointDataTask(String title, String content, String systemCode, List<String> pointIds, List<QmsPointTimeSegmentEnum> tmsegs,
                                                              LocalDateTime beginTime, LocalDateTime endTime, int userId, String userName) {
        return null;
    }

    public ManualTaskOperateResultDto addGenerateExportFileTask() {
        return null;
    }

    public ManualTaskOperateResultDto addGenerateArchiveReportTask() {
        return null;
    }

    /**
     * 设置指定的任务WBS为开始，自动设置任务的状态为执行中、执行开始时间为当前时间
     *
     * @param wbsid 任务分解项ID
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/30
     */
    public ManualTaskOperateResultDto startWbsExecute(String wbsid) {
        //初始化返回结果，先设置是否成功为false、各数量均为0
        ManualTaskOperateResultDto result = new ManualTaskOperateResultDto();
        result.setSuccess(false);
        result.setSuccesscount(0x0);
        result.setFailcount(0x0);
        result.setCancelcount(0x0);

        if (StringUtils.isBlank(wbsid)) {
            result.setMsg("任务分解项ID不能为空");
            return result;
        }
        //先查询WBS是否存在， 并获取其中的任务ID
        String taskid = null;
        LambdaQueryWrapper<QmsManualTaskWbs> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(QmsManualTaskWbs::getTaskid, QmsManualTaskWbs::getTaskstatus);
        queryWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
        QmsManualTaskWbs en = manualTaskWbsRepository.selectOne(queryWrapper);
        if (en == null) {
            result.setMsg("任务分解项ID错误，任务分解项不存在");
            return result;
        } else {
            taskid = en.getTaskid();
            //判断wbs的执行状态，只有待执行的才能取消/终止
            //在此不判断状态，实际不对wbs的数据产生修改，保持返回结果为成功
        }

        LocalDateTime now = LocalDateTimeUtil.getNow();
        LambdaUpdateWrapper<QmsManualTaskWbs> updateWrapper = new LambdaUpdateWrapper<>();
        //开始执行:修改任务WBS的状态为执行中
        //设置执行状态为执行中、执行开始时间设置为当前时间
        updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PROCESSING);
        updateWrapper.set(QmsManualTaskWbs::getExecbegintm, now);
        //设置更新时间为当前时间
        updateWrapper.set(QmsManualTaskWbs::getUptm, now);

        //条件：id相等、任务状态原先为待执行
        updateWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
        updateWrapper.eq(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PENDING);

        int count = manualTaskWbsRepository.update(null, updateWrapper);

        if (count > 0x0) {
            //设置返回结果成功标记为true
            result.setSuccess(true);

            //根据任务WBS中的状态更新任务信息中的执行信息
            //实际对任务WBS产生影响时才对任务的数量和状态进行更新
            updateTaskExecuteInfo(taskid);
        } else {
            //没有受影响的任务WBS，没有受影响的任务WBS也返回成功（因为可能实际确实是满足条件的任务WBS，无需进行任务WBS的执行信息修改）
            //设置返回结果成功标记为true
            result.setSuccess(true);
        }

        //设置返回结果中的任务ID和WBSID
        result.setTaskid(taskid);
        result.setWbsid(wbsid);
        //查询任务信息，对返回结果中的总数、成功数量、失败数量、取消数量进行赋值
        queryTaskExecuteCounts(result);

        return result;
    }

    /**
     * 设置指定的任务WBS为执行结束，根据传入的是否成功标记设置任务的状态为执行成功或执行时间、执行截止时间为当前时间并计算耗时
     *
     * @param wbsid 任务分解项ID
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/30
     */
    public ManualTaskOperateResultDto endWbsExecute(String wbsid, boolean success, String executeResult) {
        //初始化返回结果，先设置是否成功为false、各数量均为0
        ManualTaskOperateResultDto result = new ManualTaskOperateResultDto();
        result.setSuccess(false);
        result.setSuccesscount(0x0);
        result.setFailcount(0x0);
        result.setCancelcount(0x0);

        if (StringUtils.isBlank(wbsid)) {
            result.setMsg("任务分解项ID不能为空");
            return result;
        }
        //先查询WBS是否存在， 并获取其中的任务ID
        String taskid = null;
        LocalDateTime executeBeginTime = null;
        LambdaQueryWrapper<QmsManualTaskWbs> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(QmsManualTaskWbs::getTaskid, QmsManualTaskWbs::getTaskstatus, QmsManualTaskWbs::getExecbegintm);
        queryWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
        QmsManualTaskWbs en = manualTaskWbsRepository.selectOne(queryWrapper);
        if (en == null) {
            result.setMsg("任务分解项ID错误，任务分解项不存在");
            return result;
        } else {
            taskid = en.getTaskid();
            executeBeginTime = en.getExecbegintm();
            //判断wbs的执行状态，只有待执行的才能取消/终止
            //在此不判断状态，实际不对wbs的数据产生修改，保持返回结果为成功
        }

        LocalDateTime now = LocalDateTimeUtil.getNow();
        LambdaUpdateWrapper<QmsManualTaskWbs> updateWrapper = new LambdaUpdateWrapper<>();
        if (success == true) {
            //执行结束并且成功
            updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.COMPLETE);
        } else {
            //执行结束但失败
            updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.FAILED);
        }
        //不管传入的执行结果是否为空均使用传入进行更新
        updateWrapper.set(QmsManualTaskWbs::getExecresult, executeResult);
        //如果有执行结束时间，判定为是执行结束；根据是否成功设置执行的结果
        updateWrapper.set(QmsManualTaskWbs::getExecendtm, now);
        //设置更新时间为当前时间
        updateWrapper.set(QmsManualTaskWbs::getUptm, now);
        //计算耗时毫秒数
        if (executeBeginTime != null && executeBeginTime.isAfter(now) == false) {
            //如果传入的执行开始和结束时间有效计算耗时毫秒数；如果2个时间相同设置耗时为0
            Duration duration = Duration.between(executeBeginTime, now);
            //获取时间差的毫秒数
            Long millis = duration.toMillis();
            updateWrapper.set(QmsManualTaskWbs::getExecmillis, millis);
        } else {
            updateWrapper.set(QmsManualTaskWbs::getExecmillis, 0.0f);
        }

        //条件：id相等、任务状态原先为执行中（只有执行中的才能修改为执行失败或执行完成）
        updateWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
        updateWrapper.eq(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PROCESSING);

        int count = manualTaskWbsRepository.update(null, updateWrapper);

        if (count > 0x0) {
            //设置返回结果成功标记为true
            result.setSuccess(true);

            //根据任务WBS中的状态更新任务信息中的执行信息
            //实际对任务WBS产生影响时才对任务的数量和状态进行更新
            updateTaskExecuteInfo(taskid);
        } else {
            //没有受影响的任务WBS，没有受影响的任务WBS也返回成功（因为可能实际确实是满足条件的任务WBS，无需进行任务WBS的执行信息修改）
            //设置返回结果成功标记为true
            result.setSuccess(true);
        }

        //设置返回结果中的任务ID和WBSID
        result.setTaskid(taskid);
        result.setWbsid(wbsid);
        //查询任务信息，对返回结果中的总数、成功数量、失败数量、取消数量进行赋值
        queryTaskExecuteCounts(result);

        return result;
    }

    /**
     * 更新任务分解表的执行信息，更新任务分解表时自动更新任务信息中的执行信息
     * 此方法是否应该有，还是均使用start和end方法
     *
     * @param wbsid            任务分解项ID
     * @param taskid           任务项ID
     * @param executeBeginTime 执行开始时间
     * @param executeEndTime   执行结束时间，为null表示没有执行完成
     * @param success          执行结果是否成功，在执行结束时间不为null时有效
     * @param executeResult    执行结果信息，在执行结束时间不为null时有效
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/29
     */
    public ManualTaskOperateResultDto setWbsExecuteInfo(String wbsid, String taskid, LocalDateTime executeBeginTime,
                                                        LocalDateTime executeEndTime, boolean success, String executeResult) {
        //初始化返回结果，先设置是否成功为false、各数量均为0
        ManualTaskOperateResultDto result = new ManualTaskOperateResultDto();
        result.setSuccess(false);
        result.setSuccesscount(0x0);
        result.setFailcount(0x0);
        result.setCancelcount(0x0);

        if (StringUtils.isBlank(wbsid)) {
            result.setMsg("任务分解项ID不能为空");
            return result;
        }
        if (StringUtils.isBlank(taskid)) {
            result.setMsg("任务ID不能为空");
            return result;
        }
        if (executeBeginTime == null) {
            result.setMsg("执行开始时间不能为空");
            return result;
        }

        LambdaUpdateWrapper<QmsManualTaskWbs> updateWrapper = new LambdaUpdateWrapper<>();
        //设置更新时间为当前时间
        updateWrapper.set(QmsManualTaskWbs::getUptm, LocalDateTimeUtil.getNow());
        if (executeEndTime == null) {
            //如果没有执行结束时间，判定为是开始执行；修改任务WBS的状态为执行中
            //设置执行状态为执行中、执行开始时间设置为传入的开始时间
            updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PROCESSING);
            updateWrapper.set(QmsManualTaskWbs::getExecbegintm, executeBeginTime);

            //条件：id相等、任务状态原先为待执行
            updateWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
            updateWrapper.eq(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PENDING);

        } else {
            //如果有执行结束时间，判定为是执行结束；根据是否成功设置执行的结果
            updateWrapper.set(QmsManualTaskWbs::getExecendtm, executeEndTime);
            //不管传入的执行结果是否为空均使用传入进行更新
            updateWrapper.set(QmsManualTaskWbs::getExecresult, executeResult);
            //计算耗时毫秒数
            if (executeBeginTime.isAfter(executeEndTime) == false) {
                //如果传入的执行开始和结束时间有效计算耗时毫秒数；如果2个时间相同设置耗时为0
                Duration duration = Duration.between(executeBeginTime, executeEndTime);
                //获取时间差的毫秒数
                Long millis = duration.toMillis();
                updateWrapper.set(QmsManualTaskWbs::getExecmillis, millis);
            } else {
                updateWrapper.set(QmsManualTaskWbs::getExecmillis, 0.0f);
            }
            if (success == true) {
                //执行结束并且成功
                updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.COMPLETE);
            } else {
                //执行结束但失败
                updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.FAILED);
            }

            //条件：id相等、任务状态原先为执行中（只有执行中的才能修改为执行失败或执行完成）
            updateWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
            updateWrapper.eq(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PROCESSING);
        }

        int count = manualTaskWbsRepository.update(null, updateWrapper);
        if (count > 0x0) {
            //设置返回结果成功标记为true
            result.setSuccess(true);

            //根据任务WBS中的状态更新任务信息中的执行信息
            //实际对任务WBS产生影响时才对任务的数量和状态进行更新
            updateTaskExecuteInfo(taskid);
        } else {
            //没有受影响的任务WBS，没有受影响的任务WBS也返回成功（因为可能实际确实是满足条件的任务WBS，无需进行任务WBS的执行信息修改）
            //设置返回结果成功标记为true
            result.setSuccess(true);
        }

        //设置返回结果中的任务ID和WBSID
        result.setTaskid(taskid);
        result.setWbsid(wbsid);
        //查询任务信息，对返回结果中的总数、成功数量、失败数量、取消数量进行赋值
        queryTaskExecuteCounts(result);

        return result;
    }

    /**
     * 查询指定任务的执行信息各数量并进行赋值
     *
     * @param operateResult 任务操作结果对象
     * @return void
     * @author QuCheng Tech
     * @since 2025/10/30
     */
    private void queryTaskExecuteCounts(ManualTaskOperateResultDto operateResult) {
        if (operateResult != null && StringUtils.isNotBlank(operateResult.getTaskid())) {
            LambdaQueryWrapper<QmsManualTask> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(QmsManualTask::getTotalcount, QmsManualTask::getSuccesscount, QmsManualTask::getFailcount, QmsManualTask::getCancelcount);
            queryWrapper.eq(QmsManualTask::getId, operateResult.getTaskid());

            QmsManualTask en = manualTaskRepository.selectOne(queryWrapper);
            if (en != null) {
                if (en.getTotalcount() != null)
                    operateResult.setTotalcount(en.getTotalcount().intValue());
                if (en.getSuccesscount() != null)
                    operateResult.setSuccesscount(en.getSuccesscount().intValue());
                if (en.getFailcount() != null)
                    operateResult.setFailcount(en.getFailcount().intValue());
                if (en.getCancelcount() != null)
                    operateResult.setCancelcount(en.getCancelcount().intValue());
            }
        }
    }

    /**
     * 取消指定的任务分解项
     *
     * @param wbsid    任务分解项ID
     * @param userId   进行取消/终止操作的用户ID
     * @param userName 进行取消/终止操作的用户名称
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/30
     */
    public ManualTaskOperateResultDto cancelWbs(String wbsid, int userId, String userName) {
        //初始化返回结果，先设置是否成功为false、各数量均为0
        ManualTaskOperateResultDto result = new ManualTaskOperateResultDto();
        result.setSuccess(false);
        result.setSuccesscount(0x0);
        result.setFailcount(0x0);
        result.setCancelcount(0x0);

        if (StringUtils.isBlank(wbsid)) {
            result.setMsg("任务分解项ID不能为空");
            return result;
        }
        //先查询WBS是否存在， 并获取其中的任务ID
        String taskid = null;
        LambdaQueryWrapper<QmsManualTaskWbs> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(QmsManualTaskWbs::getTaskid, QmsManualTaskWbs::getTaskstatus);
        queryWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
        QmsManualTaskWbs en = manualTaskWbsRepository.selectOne(queryWrapper);
        if (en == null) {
            result.setMsg("任务分解项ID错误，任务分解项不存在");
            return result;
        } else {
            taskid = en.getTaskid();
            //判断wbs的执行状态，只有待执行的才能取消/终止
            //在此不判断状态，实际不对wbs的数据产生修改，保持返回结果为成功
        }

        LambdaUpdateWrapper<QmsManualTaskWbs> updateWrapper = new LambdaUpdateWrapper<>();
        //设置任务状态为取消、更新时间为当前时间
        updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.CANCELLED);
        updateWrapper.set(QmsManualTaskWbs::getUptm, LocalDateTimeUtil.getNow());
        if (userId > 0x0)
            updateWrapper.set(QmsManualTaskWbs::getCanceluserid, userId);
        //不管传入的取消用户名称是否为空，均进行赋值
        updateWrapper.set(QmsManualTaskWbs::getCancelusername, userName);

        //条件：id相等、任务状态原先为待执行（执行中的任务表示已经在执行最终会执行成功或执行失败，执行中的任务无法进行中断/终止）
        updateWrapper.eq(QmsManualTaskWbs::getWbsid, wbsid);
        updateWrapper.eq(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PENDING);

        int count = manualTaskWbsRepository.update(null, updateWrapper);
        if (count > 0x0) {
            //设置返回结果成功标记为true
            result.setSuccess(true);

            //根据任务WBS中的状态更新任务信息中的执行信息
            //实际对任务WBS产生影响时才对任务的数量和状态进行更新
            updateTaskExecuteInfo(taskid);
        } else {
            //没有受影响的任务WBS，没有受影响的任务WBS也返回成功（因为可能实际确实是满足条件的任务WBS，无需进行任务WBS的执行信息修改）
            //设置返回结果成功标记为true
            result.setSuccess(true);
        }

        //设置返回结果中的任务ID和WBSID
        result.setTaskid(taskid);
        result.setWbsid(wbsid);
        //查询任务信息，对返回结果中的总数、成功数量、失败数量、取消数量进行赋值
        queryTaskExecuteCounts(result);

        return result;
    }

    /**
     * 取消指定的任务，所有未执行的任务分解项均取消执行
     *
     * @param taskid   任务ID
     * @param userId   进行取消/终止操作的用户ID
     * @param userName 进行取消/终止操作的用户名称
     * @return qc.module.qms.dto.task.ManualTaskOperateResultDto
     * @author QuCheng Tech
     * @since 2025/10/30
     */
    public ManualTaskOperateResultDto cancelTask(String taskid, int userId, String userName) {
        //初始化返回结果，先设置是否成功为false、各数量均为0
        ManualTaskOperateResultDto result = new ManualTaskOperateResultDto();
        result.setSuccess(false);
        result.setSuccesscount(0x0);
        result.setFailcount(0x0);
        result.setCancelcount(0x0);

        if (StringUtils.isBlank(taskid)) {
            result.setMsg("任务ID不能为空");
            return result;
        }

        LambdaUpdateWrapper<QmsManualTaskWbs> updateWrapper = new LambdaUpdateWrapper<>();
        //设置任务状态为取消、更新时间为当前时间
        updateWrapper.set(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.CANCELLED);
        updateWrapper.set(QmsManualTaskWbs::getUptm, LocalDateTimeUtil.getNow());
        if (userId > 0x0)
            updateWrapper.set(QmsManualTaskWbs::getCanceluserid, userId);
        //不管传入的取消用户名称是否为空，均进行赋值
        updateWrapper.set(QmsManualTaskWbs::getCancelusername, userName);

        //条件：id相等、任务状态原先为待执行（执行中的任务表示已经在执行最终会执行成功或执行失败，执行中的任务无法进行中断/终止）
        updateWrapper.eq(QmsManualTaskWbs::getTaskid, taskid);
        updateWrapper.eq(QmsManualTaskWbs::getTaskstatus, QmsManualTaskStatusEnum.PENDING);

        int count = manualTaskWbsRepository.update(null, updateWrapper);
        if (count > 0x0) {
            //设置返回结果成功标记为true
            result.setSuccess(true);

            //根据任务WBS中的状态更新任务信息中的执行信息
            //实际对任务WBS产生影响时才对任务的数量和状态进行更新
            updateTaskExecuteInfo(taskid);
        } else {
            //没有受影响的任务WBS，没有受影响的任务WBS也返回成功（因为可能实际确实是满足条件的任务WBS，无需进行任务WBS的执行信息修改）
            //设置返回结果成功标记为true
            result.setSuccess(true);
        }

        //设置返回结果中的任务ID和WBSID
        result.setTaskid(taskid);
        //result.setWbsid(wbsid);//针对整个任务进行取消/终止，不需要设置返回结果中的wbsid
        //查询任务信息，对返回结果中的总数、成功数量、失败数量、取消数量进行赋值
        queryTaskExecuteCounts(result);

        return result;
    }

    /**
     * 更新指定任务的执行信息，包含任务状态、执行起始和截止时间、成功数量、失败数量、取消数量
     *
     * @param taskid 任务ID
     * @return void
     * @author QuCheng Tech
     * @since 2025/10/29
     */
    private void updateTaskExecuteInfo(String taskid) {
        if (StringUtils.isNotBlank(taskid)) {
            //查询任务的所有WBS，根据每个WBS的执行状态和时间进行判断处理
            LambdaQueryWrapper<QmsManualTaskWbs> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(QmsManualTaskWbs::getTaskstatus, QmsManualTaskWbs::getExecbegintm, QmsManualTaskWbs::getExecendtm);
            queryWrapper.eq(QmsManualTaskWbs::getTaskid, taskid);

            List<QmsManualTaskWbs> ens = manualTaskWbsRepository.selectList(queryWrapper);
            if (ens != null && ens.size() > 0x0) {
                //如果查询到的WBS集合为空，判定为数据错误，不对任务表中的信息进行更新
                int processingCount = 0x0;
                int successCount = 0x0;
                int failCount = 0x0;
                int cancelCount = 0x0;
                LocalDateTime minExecuteTime = null;
                LocalDateTime maxExecuteTime = null;
                for (QmsManualTaskWbs en : ens) {
                    if (en.getTaskstatus() == QmsManualTaskStatusEnum.PROCESSING)
                        processingCount++;
                    else if (en.getTaskstatus() == QmsManualTaskStatusEnum.COMPLETE)
                        successCount++;
                    else if (en.getTaskstatus() == QmsManualTaskStatusEnum.FAILED)
                        failCount++;
                    else if (en.getTaskstatus() == QmsManualTaskStatusEnum.CANCELLED)
                        cancelCount++;

                    if (en.getExecbegintm() != null) {
                        if (minExecuteTime == null || minExecuteTime.isAfter(en.getExecbegintm()) == true)
                            minExecuteTime = en.getExecbegintm();
                    }
                    if (en.getExecendtm() != null) {
                        if (maxExecuteTime == null || en.getExecendtm().isAfter(maxExecuteTime) == true)
                            maxExecuteTime = en.getExecendtm();
                    }
                }

                LambdaUpdateWrapper<QmsManualTask> updateWrapper = new LambdaUpdateWrapper<>();
                //设置更新时间为当前时间
                updateWrapper.set(QmsManualTask::getUptm, LocalDateTimeUtil.getNow());
                //设置执行起始时间、成功数量、失败数量和取消数量
                updateWrapper.set(QmsManualTask::getExecbegintm, minExecuteTime);
                updateWrapper.set(QmsManualTask::getSuccesscount, successCount);
                updateWrapper.set(QmsManualTask::getFailcount, failCount);
                updateWrapper.set(QmsManualTask::getCancelcount, cancelCount);
                //任务的状态赋值
                if (processingCount + successCount + failCount + cancelCount == 0x0) {
                    //所有的数量均为0，任务WBS全部都是待执行
                    updateWrapper.set(QmsManualTask::getTaskstatus, QmsManualTaskStatusEnum.PENDING);
                } else if (successCount + failCount + cancelCount == ens.size()) {
                    //所有任务WBS均为：执行失败、执行完成、终止/取消；没有待执行或执行中的WBS
                    //判断是否任务WBS全部为一种状态，如果任务WBS有多种状态设置为执行完成
                    if (successCount == ens.size())
                        updateWrapper.set(QmsManualTask::getTaskstatus, QmsManualTaskStatusEnum.COMPLETE);
                    else if (failCount == ens.size())
                        updateWrapper.set(QmsManualTask::getTaskstatus, QmsManualTaskStatusEnum.FAILED);
                    else if (cancelCount == ens.size())
                        updateWrapper.set(QmsManualTask::getTaskstatus, QmsManualTaskStatusEnum.CANCELLED);
                    else
                        updateWrapper.set(QmsManualTask::getTaskstatus, QmsManualTaskStatusEnum.COMPLETE);
                } else {
                    //至少有1个WBS是在执行中，设置任务状态为执行中
                    updateWrapper.set(QmsManualTask::getTaskstatus, QmsManualTaskStatusEnum.PROCESSING);
                }

                //条件：任务id相等
                updateWrapper.eq(QmsManualTask::getId, taskid);

                manualTaskRepository.update(null, updateWrapper);
            }
        }
    }
}
